/*
 * PhotonRTOS础光实时操作系统 -- 处理器相关
 *
 * Copyright (C) 2022, 2023 国科础石(重庆)软件有限公司
 *
 * 作者: Baoyou Xie <xiebaoyou@kernelsoft.com>
 *
 * License terms: GNU General Public License (GPL) version 3
 *
 */

#ifndef __ASM_PROCESSOR_H
#define __ASM_PROCESSOR_H

#ifndef __ASSEMBLY__

#include <asm/types.h>

#define IS_BIT_OFFSET 9

struct task_spot {
	/**
	 * arch tc397 上下文切换需要
	 */
	void *pcxi;
};


typedef struct UCX          /* TC upper context structure */
{
	uint32_t      _PCXI;            /* upper context PCXI         */
	uint32_t      _PSW;             /* upper context PSW          */
	uint32_t      _A10;             /* upper context A10 (SP)     */
	uint32_t      _A11;             /* upper context A11 (RA)     */
	uint32_t      _D8;              /* upper context D8           */
	uint32_t      _D9;              /* upper context D9           */
	uint32_t      _D10;             /* upper context D10          */
	uint32_t      _D11;             /* upper context D11          */
	uint32_t      _A12;             /* upper context A12          */
	uint32_t      _A13;             /* upper context A13          */
	uint32_t      _A14;             /* upper context A14          */
	uint32_t      _A15;             /* upper context A15          */
	uint32_t      _D12;             /* upper context D12          */
	uint32_t      _D13;             /* upper context D13          */
	uint32_t      _D14;             /* upper context D14          */
	uint32_t      _D15;             /* upper context D15          */
} UCX_t;

typedef struct LCX          /* TC lower context structure */
{
	uint32_t      _PCXI;            /* lower context PCXI         */
	uint32_t      _A11;              /* lower context saved PC     */
	uint32_t      _A2;              /* lower context A2           */
	uint32_t      _A3;              /* lower context A3           */
	uint32_t      _DD0;              /* lower context D0           */
	uint32_t      _D1;              /* lower context D1           */
	uint32_t      _D2;              /* lower context D2           */
	uint32_t      _D3;              /* lower context D3           */
	uint32_t      _A4;              /* lower context A4           */
	uint32_t      _A5;              /* lower context A5           */
	uint32_t      _A6;              /* lower context A6           */
	uint32_t      _A7;              /* lower context A7           */
	uint32_t      _D4;              /* lower context D4           */
	uint32_t      _D5;              /* lower context D5           */
	uint32_t      _D6;              /* lower context D6           */
	uint32_t      _D7;              /* lower context D7           */
} LCX_t;

#define GET_PHYS_ADDRESS(effectiveAddr)   ((uint32_t)((uint32_t)(effectiveAddr & 0xF0000u) << 12u) | \
                                           (uint32_t)((uint32_t)(effectiveAddr & 0xFFFFu) << 6u))

#define GET_EFFECTIVE_ADDRESS(physAddr)   ((uint32_t)((uint32_t)(physAddr & 0xF0000000u) >> 12u) | \
                                           (uint32_t)((uint32_t)(physAddr & 0x003FFFC0u) >> 6u))

#define PCXI_PCX_OFFSET       (0u)
#define PCXI_PCX_MASK         (0xFFFFFu << PCXI_PCX_OFFSET)

#define PCXI_UL_OFFSET        (20u)
#define PCXI_UL_MASK          (1u << PCXI_UL_OFFSET)
#define PCXI_UL_UPPER_CTX     (PCXI_UL_MASK)
#define PCXI_UL_LOWER_CTX     (0u)

#define PCXI_PIE_OFFSET       (21u)
#define PCXI_PIE_MASK         (1u << PCXI_PIE_OFFSET)
#define PCXI_PIE_ENABLED      (PCXI_PIE_MASK)
#define PCXI_PIE_DISABLED     (0u)

#define PCXI_PCPN_OFFSET      (22u)
#define PCXI_PCPN_MASK        (0xFFu << PCXI_PCPN_OFFSET)

/** \brief Create PCXI value for and upper task context */
#define GET_UPPER_CTX_LINK(link)  (((uint32_t)(link & PCXI_PCX_MASK)) | PCXI_UL_UPPER_CTX | PCXI_PIE_ENABLED)

/** \brief Create PCXI value for and lower task context */
#define GET_LOWER_CTX_LINK(link)  (((uint32_t)(link & PCXI_PCX_MASK)) | PCXI_UL_LOWER_CTX | PCXI_PIE_ENABLED)

/*
	prefetch(x) attempts to pre-emptively get the memory pointed to
	by address "x" into the CPU L1 cache.
	prefetch(x) should not cause any kind of exception, prefetch(0) is
	specifically ok.

	prefetch() should be defined by the architecture, if not, the
	#define below provides a no-op define.

	There are 3 prefetch() macros:

	prefetch(x)  	- prefetches the cacheline at "x" for read
	prefetchw(x)	- prefetches the cacheline at "x" for write
	spin_lock_prefetch(x) - prefetches the spinlock *x for taking

	there is also PREFETCH_STRIDE which is the architecure-preferred
	"lookahead" size for prefetching streamed operations.
*/
#define ARCH_FUN_cpu_do_idle_DEFINED
extern void cpu_do_idle(void);

#endif /* __ASSEMBLY__ */

#endif /* __ASM_PROCESSOR_H */
